﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Space
{
    class Option
    {
        public string text;
        public bool enabled;
        public string command;
        public string argument;

        public Option(string text, string command, string argument = "")
        {
            this.text = text;
            this.command = command;
            this.argument = argument;
        }
    }

    enum ScreenAction
    {
        Open, Close
    }

    class Screen
    {
        int high;
        List<Option> options = new List<Option>();
        public List<Option> Options { get { return options; } }

        public Option SelectedOption { get { return options[high]; } }

        public ScreenAction Action { get; set; }

        float cap;

        float timer = 0;

        public delegate void TransitionFinishedHandler(Screen sender);
        public event TransitionFinishedHandler TransitionFinished;

        Game Game { get; set; }

        public Screen(Game game)
        {
            Game = game;
        }

        public Screen(Game game, params Option[] options) : this(game)
        {
            this.options.AddRange(options);
        }

        public void Update(float time)
        {
            if (Action == ScreenAction.Open)
            {
                timer += time;
            }
            else if (Action == ScreenAction.Close)
            {
                timer -= time;
            }
            if (cap == 0 && timer < cap) timer = cap;
            if (cap > 0 && timer > cap) timer = cap;
        }

        public void ResetIndex()
        {
            high = 0;
        }

        public void Navigate(int i)
        {
            if (i < 0)
            {
                high += i;
                while (high < 0) high += options.Count;
            }
            else
                high = (high + i) % options.Count;
        }

        public void DrawOptions3D(SpriteBatch spriteBatch, SpriteFont font)
        {

            float height = 2;

            float fieldOfView = MathHelper.ToRadians(45);
            float distance = 15;
            float aspect = Game.GraphicsDevice.Viewport.AspectRatio;

            float buttonWidth = 4.55f;
            float buttonHeight = 2.35f;

            int buttonScreenWidth = 10 * 250 / (int)distance;

            for (int i = 0; i < options.Count; i++)
            {
                Option opt = options[i];

                float startTime = i * 0.1f;
                float duration = 0.5f;
                float progress = (timer - startTime) / duration;

                if (progress < 0) progress = 0;
                if (progress > 1) progress = 1;

                if (Action == ScreenAction.Open && progress == 1 && i == options.Count - 1)
                {
                    cap = timer;
                    if (TransitionFinished != null)
                        TransitionFinished(this);
                }
                if (Action == ScreenAction.Close && progress == 0 && i == 0)
                {
                    cap = timer;
                    if (TransitionFinished != null)
                        TransitionFinished(this);
                }

                float rotationAngle = MathHelper.Pi * (1-progress);

                Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView(fieldOfView, aspect, 0.1f, 50);
                Matrix viewMatrix = Matrix.CreateLookAt(Vector3.Backward * distance, Vector3.Zero, Vector3.Up);
                Matrix worldMatrix = Matrix.CreateRotationY(rotationAngle) * Matrix.CreateTranslation(new Vector3(-distance * (float)Math.Tan(fieldOfView / 2) * aspect, distance * (float)Math.Tan(fieldOfView / 2) - (i +0.5f) * buttonHeight - height, 0));
                foreach (ModelMesh mesh in Game.Content.Load<Model>("models/buttonFrame").Meshes)
                {
                    foreach (Effect effect in mesh.Effects)
                    {
//                        effect.CurrentTechnique = effect.Techniques["Technique1Logluv"];
                        effect.CurrentTechnique = effect.Techniques["Technique1"];
                        effect.Parameters["World"].SetValue(worldMatrix);
                        effect.Parameters["Projection"].SetValue(projectionMatrix);
                        effect.Parameters["View"].SetValue(viewMatrix);
                        effect.Parameters["DiffuseColor"].SetValue(Color.LightGray.ToVector3());
                        //effect.Parameters["Texture"].SetValue(textures["flagtex"]);
                        effect.Parameters["EmissiveColor"].SetValue(Color.Black.ToVector3());
                        effect.Parameters["Light1Direction"].SetValue(Vector3.Left);
                    }
                    mesh.Draw();
                }

                if (progress == 1)
                {
                    string text = options[i].text;
                    Vector2 pos;
                    Vector3 p1 = Game.GraphicsDevice.Viewport.Project(Vector3.Zero, projectionMatrix, viewMatrix, worldMatrix);
                    pos.X = p1.X;
                    pos.Y = p1.Y;
                    pos.Y -= font.LineSpacing / 2;

                    pos.X += (buttonScreenWidth - font.MeasureString(text).X) / 2;
                    spriteBatch.Begin();
                    spriteBatch.DrawString(font, text, pos, high == i ? Color.HotPink : Color.LightBlue);
                    spriteBatch.End();
                }
            }
        }

        public void DrawOptions(SpriteBatch spriteBatch, SpriteFont font, Rectangle rectangle)
        {
            Vector2 pos = new Vector2(rectangle.X, rectangle.Y);

            for (int i = 0; i < options.Count; i++)
            {
                Option opt = options[i];
                string text = opt.enabled ? "X " + opt.text : opt.text;
                spriteBatch.DrawString(font, text, pos, high == i ? Color.Red : Color.Beige);
                pos.Y += font.LineSpacing;

                DrawButton(spriteBatch, font, text, new Rectangle((int)pos.X, (int)pos.Y, (int)rectangle.Width, 80));
            }
        }

        void DrawButton(SpriteBatch spriteBatch, SpriteFont font, string text, Rectangle rectangle)
        {
            spriteBatch.Draw(Game.Content.Load<Texture2D>("textures/button"), rectangle, Color.White);
            Vector2 size = font.MeasureString(text);
            spriteBatch.DrawString(font, text, new Vector2(rectangle.X + (rectangle.Width - size.X) / 2, rectangle.Y + (rectangle.Height - size.Y)), Color.Black);
        }
    }
}
